import java.util.Stack;

public class SymbolTable {
    Stack<Symbol> table;

    public SymbolTable(){
        table = new Stack<Symbol>();
        TypeSym typeint = new TypeSym("int", "null", 0, -1);
        TypeSym typevoid = new TypeSym("void", "null", 0, -1);
        TypeSym typeshort = new TypeSym("short", "null", 0, -1);
        table.push(typeint);
        table.push(typevoid);
        table.push(typeshort);
    }

    //Will attempt to push a symbol onto the stack. If there is a conflict,
    //it will fail to push the symbol and return false. Else returns true.
    public boolean add(Symbol sym)
    {
        for(Symbol e : table)
        {
            if(sym.name.equals(e.name)){
                if((sym.classification.equals("VAR") || sym.classification.equals("CONST")) &&
                   (e.classification.equals("VAR") || e.classification.equals("CONST")))
                {
                    //check lexlevel
                    if(sym.lexLevel == e.lexLevel)
                        return false;
                }
                else if(sym.classification.equals("TYPE") && e.classification.equals("TYPE"))
                {
                    if(sym.lexLevel == e.lexLevel)
                        return false;
                }
                else if(sym.classification.equals("PROCEDURE") && e.classification.equals("PROCEDURE"))
                    return false;

            }
        }
        table.push(sym);
        return true;
    }

    public boolean isDefined(String name, String classification, int lexLevel)
    {
        for(Symbol s : table)
        {
           if(name.equals(s.name)){
                if((classification.equals("VAR") || classification.equals("CONST")) &&
                   (classification.equals("VAR") || classification.equals("CONST")))
                {
                    //check lexlevel
                    if(lexLevel >= s.lexLevel)
                        return true;
                }
                else if(classification.equals("TYPE") && s.classification.equals("TYPE"))
                {
                    if(lexLevel >= s.lexLevel)
                        return true;
                }
                else if(classification.equals("PROCEDURE") && s.classification.equals("PROCEDURE"))
                    return true;
           }
        }
        return false;
    }

    public Symbol lookUp(String name, String classification)
    {
        for(int i = table.size()-1; i >= 0; i--)
        //for(int i = 0; i < table.size(); i++)
        {
            //System.out.print(i);
            Symbol s = table.get(i);
           if(name.equals(s.name)){
                if((s.classification.equals("VAR") || s.classification.equals("CONST")) &&
                   (classification.equals("VAR") || classification.equals("CONST")))
                {
                    return s;
                }
                else if(s.classification.equals("TYPE") && classification.equals("TYPE"))
                {
                    return s;
                }
                else if(s.classification.equals("PROCEDURE") && classification.equals("PROCEDURE"))
                    return s;
           }
        }
        return null;
    }

    public void popTopLexLevel()
    {
        int topLexLevel = table.peek().lexLevel;
        if(topLexLevel == 0)
            return;
        else
            while(table.peek().lexLevel == topLexLevel)
                table.pop();
    }

    public Symbol peek()
    {
        return table.peek();
    }
    
    
}
